import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        final int MAX_SCAN = 5_000_000;
        final int USER_COUNT = 10000;
        final int SCAN_PER_USER_MAX = 6000;
        Map<String, AtomicInteger> lastWinDrawNum = new ConcurrentHashMap<>();

        AtomicInteger totalScan = new AtomicInteger(0);
        AtomicInteger totalDraws = new AtomicInteger(0);
        Map<String, AtomicInteger> resultCount = new ConcurrentHashMap<>();

        // 记录每个奖等的所有中奖抽奖序号
        Map<String, List<Integer>> prizeDrawNums = new ConcurrentHashMap<>();

        LotterySystem lottery = new LotterySystem();
        List<User> users = new ArrayList<>();
        for (int i = 0; i < USER_COUNT; i++) {
            users.add(new User(i + 1));
        }

        ExecutorService pool = Executors.newFixedThreadPool(32);
        CountDownLatch latch = new CountDownLatch(USER_COUNT);

        for (User user : users) {
            pool.submit(() -> {
                Random rand = new Random();
                while (user.scanCount < SCAN_PER_USER_MAX && totalScan.get() < MAX_SCAN) {
                    int scan = rand.nextInt(3) + 1;
                    scan = Math.min(scan, SCAN_PER_USER_MAX - user.scanCount);
                    int remain = MAX_SCAN - totalScan.get();
                    if (scan > remain)
                        scan = remain;
                    if (scan <= 0)
                        break;
                    if (totalScan.addAndGet(scan) > MAX_SCAN) {
                        totalScan.addAndGet(-scan);
                        break;
                    }
                    user.scanCount += scan;
                    user.drawChances += scan;

                    while (user.drawChances > 0) {
                        user.drawChances--;
                        int drawNum = totalDraws.incrementAndGet();
                        String prize = lottery.draw(user, drawNum);
                        resultCount.computeIfAbsent(prize, k -> new AtomicInteger(0)).incrementAndGet();
                        if (isPhysicalPrize(prize)) {
                            int last = lastWinDrawNum.getOrDefault(prize, new AtomicInteger(0)).get();
                            int interval = drawNum - last;
                            System.out.printf("第%d次抽奖，用户ID:%d 抽到实体奖：%s，距上次中奖间隔：%d 次\n", drawNum,
                                user.id, prize, interval);
                            lastWinDrawNum.put(prize, new AtomicInteger(drawNum));
                            // 记录中奖抽奖序号
                            prizeDrawNums.computeIfAbsent(prize, k -> Collections.synchronizedList(new ArrayList<>())).add(drawNum);
                        }
                        if (prize.endsWith("积分")) {
                            int point = Integer.parseInt(prize.replace("积分", ""));
                            user.points += point;
                            // 每满40分额外增加一次抽奖机会
                            user.drawChances += user.points / 40;
                            user.points = user.points % 40;
                        }
                    }
                }
                latch.countDown();
            });
        }

        latch.await();
        pool.shutdown();

        System.out.println("总扫码次数：" + totalScan.get());
        System.out.println("总抽奖次数：" + totalDraws.get());
        for (Map.Entry<String, AtomicInteger> entry : resultCount.entrySet()) {
            System.out.printf("%s：%d 次，概率：%.2f%%\n", entry.getKey(), entry.getValue().get(),
                entry.getValue().get() * 100.0 / totalDraws.get());
        }

        // 按奖等输出所有中奖抽奖序号
//        System.out.println("\n各奖等中奖抽奖序号：");
        String[] prizeOrder = {"一等奖", "二等奖", "三等奖", "四等奖", "五等奖", "六等奖", "七等奖", "八等奖", "九等奖"};
//        for (String prize : prizeOrder) {
//            List<Integer> nums = prizeDrawNums.get(prize);
//            if (nums != null && !nums.isEmpty()) {
//                System.out.print(prize + "：");
//                for (int n : nums) {
//                    System.out.print("第" + n + "次抽奖抽中，");
//                }
//                System.out.println();
//            }
//        }

        // 输出到文件
        try (FileWriter writer = new FileWriter("prize_draw_nums.txt")) {
            for (String prize : prizeOrder) {
                List<Integer> nums = prizeDrawNums.get(prize);
                if (nums != null && !nums.isEmpty()) {
                    writer.write(prize + "：\n");
                    for (int n : nums) {
                        writer.write(n+"\n");
                    }
                    writer.write("\n");
                }
            }
            System.out.println("各奖等中奖抽奖序号已输出到 prize_draw_nums.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static boolean isPhysicalPrize(String prize) {
        return prize.endsWith("等奖");
    }
}